/* @LICENSE(NICTA_CORE) */

/*
 * Platform-specific putchar implementation.
 */

#include <stdint.h>
#include <stdio.h>

/*
 * Place a character to the given stream, which we always assume to be
 * 'stdout'.
 */
extern int
__fputc(int c, FILE *stream);

/* iMX31 UART physical address. */
#define UART_PADDR 0x43f90000
#define UART_PPTR UART_PADDR

#define URXD  0x00 /* UART Receiver Register */
#define UTXD  0x40 /* UART Transmitter Register */
#define UCR1  0x80 /* UART Control Register 1 */
#define UCR2  0x84 /* UART Control Register 2 */
#define UCR3  0x88 /* UART Control Register 3 */
#define UCR4  0x8c /* UART Control Register 4 */
#define UFCR  0x90 /* UART FIFO Control Register */
#define USR1  0x94 /* UART Status Register 1 */
#define USR2  0x98 /* UART Status Register 2 */
#define UESC  0x9c /* UART Escape Character Register */
#define UTIM  0xa0 /* UART Escape Timer Register */
#define UBIR  0xa4 /* UART BRM Incremental Register */
#define UBMR  0xa8 /* UART BRM Modulator Register */
#define UBRC  0xac /* UART Baud Rate Counter Register */
#define ONEMS 0xb0 /* UART One Millisecond Register */
#define UTS   0xb4 /* UART Test Register */

#define UART_REG(x) ((volatile uint32_t *)(UART_PPTR+(x)))
#define BIT(x) (1 << (x))

enum UARTControlBits {
    UART_SR1_TRDY = 13
};

int
__fputc(int c, FILE *stream)
{
    /* Wait until UART ready for the next character. */
    while (!(*UART_REG(USR1) & BIT(UART_SR1_TRDY)));

    /* Add character to the buffer. */
    *UART_REG(UTXD) = c;

    /* Send '\r' after every '\n'. */
    if (c == '\n')
        (void)__fputc('\r', stream);

    return 0;
}
